package com.gszy.auth.mvc;

import javax.imageio.IIOException;
import java.awt.*;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;

/**
 * @author MeUChT
 */
public class ClassUtils {
    /**
     * 读取指定包下所有被@Controller 修饰的类对象
     */

    public static Set<Class<?>> getControllerClass(String packageName){
        //获取当前包下所有的类对象
        Set<Class<?>> classSet = getClassSet(packageName);

        //准备筛选需要的Controller对象
        Set<Class<?>> controllerSet = new HashSet<>();

        for (Class<?> clazz : classSet) {
            if (clazz.isAnnotationPresent(Controller.class)){
                controllerSet.add(clazz);
            }
        }
        return controllerSet;

    }

    /**
     * 读取指定包下所有的类对象
     */

    private static Set<Class<?>> getClassSet(String packageName) {
        if (packageName == null){
            return null;
        }
        Set<Class<?>> classSet = new HashSet<>();
        String packagePath = packageName.replaceAll("\\.","/");
        try {
            //获取指定目录下所有的文件
            Enumeration<URL> resources = Thread.currentThread().getContextClassLoader().getResources(packagePath);
            while (resources.hasMoreElements()){
                URL url = resources.nextElement();
                if (url != null ){
                    //获取当前资源的协议名
                    String protocol = url.getProtocol();
                    if ("file".equals(protocol)){
                        String filePath = URLDecoder.decode(url.getFile(),"utf-8");
                        //读取文件或者文件夹成为类对象集合
                        findClassByFile(packageName,filePath,classSet);
                    }
                }
            }
        }catch (IOException e) {
            e.printStackTrace();
        }

        return classSet;
    }

    /**
     * 读取文件结构 加载文件夹下所有的.class类文件成为类对象 并且在Set 类对象集合中
     * @param packageName 包名
     * @param filePath 路径名
     * @param classSet 类对象集合
     */
    private static void findClassByFile(String packageName, String filePath, Set<Class<?>> classSet) {
        //对当前文件夹下面的文件做筛选 需要.class 需要文件夹

        File[] files = new File(filePath).listFiles(new FileFilter() {
            @Override
            public boolean accept(File file) {
                boolean directory = file.isDirectory();
                boolean clazz = file.getName().endsWith(".class");
                return directory || clazz;

            }
        });
        for (File file : files){
            String name = file.getName();
            if (file.isDirectory()){
                //子包名
                String subPackage = packageName +"."+name;

                String subFile  = file.getAbsolutePath();
                findClassByFile(subPackage,subFile,classSet);

            }else {

                String className = packageName + "." +name.replace(".class","").trim();

                //加载类对象
                try {
                    Class<?> clazz = Class.forName(className,false,Thread.currentThread().getContextClassLoader());
                    classSet.add(clazz);
                } catch (ClassNotFoundException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
